import java.awt.*;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class Solution391 {

    private List<Integer>[] getAllPoint(int[] rec){
        int x1 = rec[0], y1 = rec[1], x2 = rec[2], y2 = rec[3];
        return (List<Integer>[]) new List<?>[]{Arrays.asList(x1, y1), Arrays.asList(x2, y2), Arrays.asList(x1, y2), Arrays.asList(x2, y1)};
    }

    private boolean checkAndRemoveCorners(Map<List<Integer>, Integer> counter, int[] rec){
        List<Integer>[] allPoints = getAllPoint(rec);
        boolean res = true;
        for (List<Integer> point : allPoints) {
            if(counter.getOrDefault(point, 0) != 1){
                res = false;
            }
            counter.remove(point);
        }
        return res;
    }

    private boolean checkEachPoint(Map<List<Integer>, Integer> counter){
        for (Integer tmpCount : counter.values()) {
            if(!(tmpCount == 2 || tmpCount == 4)){
                return false;
            }
        }
        return true;
    }

    public boolean isRectangleCover(int[][] rectangles) {
        Map<List<Integer>, Integer> counter = new HashMap<>();
        long area = 0;
        int minX = Integer.MAX_VALUE, maxX = Integer.MIN_VALUE, minY = Integer.MAX_VALUE, maxY = Integer.MIN_VALUE;
        for (int[] rec : rectangles) {
            int x1 = rec[0], y1 = rec[1], x2 = rec[2], y2 = rec[3];
            minX = Math.min(minX, x1);
            minY = Math.min(minY, y1);
            maxX = Math.max(maxX, x2);
            maxY = Math.max(maxY, y2);
            area += (y2 - y1) * (x2 - x1);
            List<Integer>[] allPoint = getAllPoint(rec);
            for (List<Integer> point : allPoint) {
                int count = counter.getOrDefault(point, 0);
                counter.put(point, count + 1);
                if(count > 3){
                    return false;
                }
            }
        }
        if(area != ((maxY - minY) * (maxX - minX))){
            return false;
        }
        if(!checkAndRemoveCorners(counter, new int[]{minX, minY, maxX, maxY})){
            return false;
        }
        if(!checkEachPoint(counter)){
            return false;
        }
        return true;
    }

    public static void main(String[] args) {
        Solution391 s = new Solution391();
        System.out.println(s.isRectangleCover(new int[][]{{1,1,3,3},{3,1,4,2},{3,2,4,4},{1,3,2,4},{2,3,3,4}}));
    }
}
